use reqwest::{Client, Result};
use serde::{de::DeserializeOwned, Deserialize, Serialize};

#[derive(Clone, Debug, Deserialize)]
pub struct WxErr {
    pub errcode: Option<u32>,
    pub errmsg: Option<String>,
}

#[derive(Clone, Debug, Deserialize)]
#[serde(untagged)]
pub enum Response<T> {
    Ok(T),
    Err(WxErr),
}

pub type WxResponse<T> = Result<Response<T>>;

#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum EnvVision {
    Trial,
    Develop,
    Release,
}
pub fn query_url<T, U>(url: T, token: U) -> String
where
    T: AsRef<str>,
    U: AsRef<str>,
{
    format!("{}?access_token={}", url.as_ref(), token.as_ref())
}

pub async fn wx_post_json<Url, T, U, S>(url: Url, token: T, req: &U) -> Result<Response<S>>
where
    Url: AsRef<str>,
    T: AsRef<str>,
    U: Serialize,
    S: DeserializeOwned,
{
    let url = query_url(url, token);
    let client = Client::new();
    client
        .post(url)
        .json(req)
        .send()
        .await?
        .json::<Response<S>>()
        .await
}

pub async fn wx_get<Url, T, S>(url: Url, token: T) -> WxResponse<S>
where
    Url: AsRef<str>,
    T: AsRef<str>,
    S: DeserializeOwned,
{
    let url = query_url(url, token);
    let client = Client::new();
    client.get(url).send().await?.json::<Response<S>>().await
}

#[derive(Clone, Debug, Deserialize)]
pub struct TransportCapacityResponse {
    pub resultcode: u32,
    pub resultmsg: String,
}
